#pragma once

#ifndef __ENTS_Component_H__
#define __ENTS_Component_H__

#include "FLOW_core/rtti.h"

class CEntity;

// To create a class derived from CComponent you must create the CMPNT_BINDINGS_LIST macro, add DECLARE_COMPONENT in the header, 
// and add DEFINE_COMPONENT in the compilation unit

#define COMPONENT_INCLUDE	#include "Component.inl"

//To be added in all the component's derived classes header
#define DECLARE_COMPONENT( ComponentClassName, ParentClassName )		\
COMPONENT_INCLUDE														\
DECLARE_RTTI_CLASS( ComponentClassName, ParentClassName )		



//To be added in all the component's derived classes compilation unit
#define DEFINE_COMPONENT( ComponentName, ParentName )								\
DEFINE_RTTI_CLASS( ComponentName, ParentName )										\
void ComponentName::CheckBindings( void ) {	CheckBindings< ComponentName >( ); }	


namespace ENTS
{
	/*!
	 * \brief Class component, base class that represents a component of a game entity
	 *
	 * Class component, base class that represents a component of a game entity
	 */
	class CComponent
	{
		DECLARE_RTTI_ROOT_CLASS( CComponent );
	protected:
		//! Pointer to the entity that owns this component, it can be null.
		CEntity*					m_p_entity;
		//! priority of the component the lesser the higher priority to update the component has
		u32_t						m_u_priority;
		//! Tells if this component has checked its bindings and all are binded
		bool_t						m_b_bindings_completed;
		//! Tells the frequency the update method of the component should be executed
		u32_t						m_u_update_freq;
		//! Tells if the component should update or not
		bool_t						m_b_enabled;
		//! Tells if the component has been initialized
		bool_t						m_b_initialized;
	public:
		//! Default constructor
		CComponent( );
		//! Virtual destructor, this class is designed to be inherited
		virtual ~CComponent();
		//! Update method, this is designed to be implemented in the derived classes
		virtual void Update( void ) = 0;
		//! Check component bindings
		virtual void CheckBindings( void ) = 0;
		//! Initialize the component
		virtual void Init( void ) = 0;
		//! Reset the component
		virtual void Reset( void ) = 0;
		//! Make a clone of the component
		virtual CComponent* Clone( void ) = 0;
		//! Tells if all the bindings of the component are completed
		bool_t BindingsCompleted( void ) const;
		//! Tells if the component is initialized or not
		bool_t IsInitialized( void ) const;
		//! Tells if the component is enabled or not
		bool_t IsEnabled( void ) const;
		//! Sets the component enabled or disabled
		void SetEnabled( bool_t ab_enabled );
		//! Gets the component's priority
		u32_t GetPriority( void ) const;
		//! Sets the entity that contains this component, maybe NULL
		void SetEntity( CEntity* ap_ent );
	};
} // end namespace ENTS
#endif